package com.smallkingson.ylib.view.utils;

import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.StateListDrawable;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.os.Handler;
import android.support.annotation.RequiresApi;
import android.text.Editable;
import android.text.Selection;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.TextPaint;
import android.text.style.CharacterStyle;
import android.text.style.ForegroundColorSpan;
import android.view.Display;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLayoutChangeListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnDrawListener;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.smallkingson.ylib.core.S;
import com.smallkingson.ylib.core.Yr;
import com.smallkingson.ylib.core.utils.YSystems;
import com.smallkingson.ylib.view.drawable.SelectorDrawable;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author yorun
 */
public class YViews {

  public static final int STATUSBAR_HEIGHT = 50;

  /**
   * 计算视频显示的宽高
   */
  public static Rect computeShowRect(int viewWidth, int viewHeight, int dstWidth, int dstHeight) {
    int width, height;
    float wRate = dstWidth * 1.0f / viewWidth;
    float hRate = dstHeight * 1.0f / viewHeight;
    if (wRate > hRate) {
      width = viewWidth;
      height = (int) (dstHeight / wRate);
      int top = (viewHeight - height) / 2;
      return new Rect(0, top, width, height + top);
    } else {
      width = (int) (dstWidth / hRate);
      height = viewHeight;
      int left = (viewWidth - width) / 2;
      return new Rect(left, 0, left + width, height);
    }
  }

  /**
   * 动态设置ListView的高度
   */
  public static void setListViewHeightBasedOnChildren(ListView listView) {
    if (listView == null) return;

    ListAdapter listAdapter = listView.getAdapter();
    if (listAdapter == null) {
      // pre-condition
      return;
    }

    int totalHeight = 0;
    for (int i = 0; i < listAdapter.getCount(); i++) {
      View listItem = listAdapter.getView(i, null, listView);
      listItem.measure(0, 0);
      totalHeight += listItem.getMeasuredHeight();
    }

    LayoutParams params = listView.getLayoutParams();
    params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
    listView.setLayoutParams(params);
  }

  public static List<Map<String, Object>> encase(String[] viewNames, List[] datas) {

    // 健壮性
    try {
      if (viewNames == null && viewNames.length == 0) {
        throw new Exception("控件名称们 的名字 不能为空 或者长度是0");
      }
      if (datas == null && datas.length == 0) {
        throw new Exception("控件们  不能为空 或者长度是0");
      }
      if (viewNames.length != datas.length) {
        throw new Exception("控件们的名字和他们的数量不匹配");
      }
    } catch (Exception e) {
      Yr.logError(e);
    }

    // 遍历这些控件每个控件取一条 放到map里面，这就要求动态生成data
    List<Map<String, Object>> viewDatas = new ArrayList<Map<String, Object>>();
    // 总循环次数 控件datas的长度
    for (int i = 0; i < datas[0].size(); i++) {

      Map<String, Object> map = new HashMap<String, Object>();

      for (int j = 0; j < viewNames.length; j++) {

        map.put(viewNames[j], datas[j].get(i));
      }
      viewDatas.add(map);
    }
    return viewDatas;
  }

  public static Map<Integer, View> getViewPocket(View view, int... viewId) {

    if (viewId == null || viewId.length == 0) {
      try {
        throw new Exception("viewId长度为空");
      } catch (Exception e) {
        Yr.logError(e);
      }
    }
    Map<Integer, View> map = new HashMap<Integer, View>();

    for (int i = 0; i < viewId.length; i++) {
      map.put(new Integer(viewId[i]), view.findViewById(viewId[i]));
    }
    return map;
  }

  public static boolean isInScope(ListView lv, int posi) {

    if (posi >= lv.getFirstVisiblePosition() && posi <= lv.getLastVisiblePosition()) {
      return true;
    }
    return false;
  }

  static Map<String, View> map = new HashMap<String, View>();

  /**
   * 获取手机屏幕的宽度 单位像素
   */
  public static int getScreenWidth(Context context) {

    WindowManager windowMgr = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Display display = windowMgr.getDefaultDisplay();
    return display.getWidth();
  }

  /**
   * 获取手机屏幕的高度 单位像素
   */
  public static int getScreenHeight(Context context) {

    WindowManager windowMgr = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Display display = windowMgr.getDefaultDisplay();
    return display.getHeight();
  }

  /**
   * 获取当前view 的宽度
   */
  public static int getViewWidth(View view) {

    return view.getLayoutParams().width;
  }

  public static int getViewHeight(View view) {

    return view.getLayoutParams().height;
  }

  public static void setViewWidth(View view, int width) {

    LayoutParams layoutParams = view.getLayoutParams();
    layoutParams.width = width;
    view.setLayoutParams(layoutParams);
  }

  public static void setViewHeight(View view, int height) {

    LayoutParams lp = null;
    if (view.getLayoutParams() == null) {
      lp = new LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
          LinearLayout.LayoutParams.WRAP_CONTENT); // ,
      // 1是可选写的
    } else {
      lp = view.getLayoutParams();
    }
    lp.height = height;
    view.setLayoutParams(lp);
  }

  /**
   * 设置view 的宽高，此方法暂时不能在view的构造方法中调用
   */
  public static void setViewWH(View view, int width, int height) {

    LayoutParams layoutParams = view.getLayoutParams();
    layoutParams.height = height;
    layoutParams.width = width;
    view.setLayoutParams(layoutParams);
  }

  /**
   * 获取当前布局在屏幕中的坐标 单位是px，此坐标表示该view最左上点的坐标
   */
  public static Point getViewOnScreenXY(View view) {

    Point ViewPoint = new Point();
    int[] XY = new int[2];
    view.getLocationOnScreen(XY);
    ViewPoint.x = XY[0];
    ViewPoint.y = XY[1];
    return ViewPoint;
  }

  /**
   * 获取id 为 content的根布局
   */
  public static FrameLayout getContentView(View v) {
    if (v.getId() == android.R.id.content) {
      return (FrameLayout) v;
    }
    View parent = (View) v.getParent();
    Yr.d(parent);
    if (parent == null) {
      return null;
    }
    return getContentView(parent);
  }

  /**
   * 获取id 为 content的根布局
   */
  public static FrameLayout getContentView(Activity activity) {

    return getContentViewByRoot((ViewGroup) activity.getWindow().getDecorView());
  }

  /**
   * 获取id 为 content的根布局
   */
  public static FrameLayout getContentViewByRoot(ViewGroup parent) {

    return (FrameLayout) parent.findViewById(android.R.id.content);
  }

  /**
   * 获取当前view父布局的宽度
   */
  public static int getParentViewWidth(View view) {

    return ((View) view.getParent()).getLayoutParams().width;
  }

  /**
   * 获取当前view父布局的高度
   */
  public static int getParentHeight(View view) {

    return ((View) view.getParent()).getLayoutParams().height;
  }

  public static void setViewMargin(View view, int left, int top, int right, int bottom) {

    LayoutParams lp = view.getLayoutParams();
    if (lp instanceof RelativeLayout.LayoutParams) {
      RelativeLayout.LayoutParams lp1 = (RelativeLayout.LayoutParams) view.getLayoutParams();
      lp1.setMargins(left, top, right, bottom);
      view.setLayoutParams(lp);
    } else if (lp instanceof LinearLayout.LayoutParams) {
      LinearLayout.LayoutParams lp1 = (LinearLayout.LayoutParams) view.getLayoutParams();
      lp1.setMargins(left, top, right, bottom);
      view.setLayoutParams(lp);
    } else {
      FrameLayout.LayoutParams lp1 = (FrameLayout.LayoutParams) view.getLayoutParams();
      lp1.setMargins(left, top, right, bottom);
      view.setLayoutParams(lp);
    }
  }

  /**
   * 当一个ViewGroup的height属性为wrap的时候 通过这个方法获取它所包含的view中最大height
   */
  public static int getChildViewMaxHeight(ViewGroup group) {

    int maxHeight = 0;
    for (int i = 0; i < group.getChildCount(); i++) {
      View v = group.getChildAt(i);
      if (v instanceof ViewGroup) {
        int height = 0;
        if (v.getLayoutParams().height == LayoutParams.WRAP_CONTENT) {
          height = getChildViewMaxHeight((ViewGroup) v);
        } else {
          height = YViews.getViewHeight(v);
        }
        if (maxHeight < height) {
          maxHeight = height;
        }
      } else if (v instanceof TextView) {
        TextView tv = (TextView) v;
        int height = 0;
        if (tv.getLayoutParams().height == LayoutParams.WRAP_CONTENT) {
          height = getTextViewbounds(tv).height();
        } else {
          height = YViews.getViewHeight(tv);
        }
        if (maxHeight < height) {
          maxHeight = height;
        }
      } else {
        int height = YViews.getViewHeight(v);
        if (maxHeight < height) {
          maxHeight = height;
        }
      }
    }
    return maxHeight;
  }

  /**
   * 当一个ViewGroup的width属性为wrap的时候 通过这个方法获取它所包含的view中最大width
   */
  public static int getChildViewMaxWidth(ViewGroup group) {

    int maxWidth = 0;

    for (int i = 0; i < group.getChildCount(); i++) {

      View v = group.getChildAt(i);

      if (v instanceof ViewGroup) {

        int width = 0;

        if (v.getLayoutParams().height == LayoutParams.WRAP_CONTENT) {

          width = getChildViewMaxWidth((ViewGroup) v);
        } else {

          width = YViews.getViewWidth(v);
        }
        if (maxWidth < width) {

          maxWidth = width;
        }
      } else if (v instanceof TextView) {

        TextView tv = (TextView) v;

        int width = 0;

        if (tv.getLayoutParams().width == LayoutParams.WRAP_CONTENT) {

          width = getTextViewbounds(tv).width();
        } else {

          width = YViews.getViewWidth(tv);
        }
        if (maxWidth < width) {

          maxWidth = width;
        }
      } else {

        int width = YViews.getViewWidth(v);

        if (maxWidth < width) {

          maxWidth = width;
        }
      }
    }
    return maxWidth;
  }

  /**
   * 当TextView的height属性为wrap时 ，获取它的宽和高的方法
   */
  public static Rect getTextViewbounds(TextView tv) {

    String text = (String) tv.getText();
    TextPaint paint = tv.getPaint();
    Rect bounds = new Rect();
    paint.getTextBounds(text, 0, text.length(), bounds);
    return bounds;
  }

  /**
   * 当TextView的height属性为wrap时 ，获取它的宽和高的方法
   */
  public static int getTextViewWidth(TextView tv) {

    String text = (String) tv.getText();
    TextPaint paint = tv.getPaint();
    Rect bounds = new Rect();
    paint.getTextBounds(text, 0, text.length(), bounds);
    return bounds.right - bounds.left;
  }

  /**
   *
   * @param parent
   * @param child
   * @return
   */
  public static Point getLocationOnParentView(View parent, View child) {

    Point cXY = getViewOnScreenXY(child);
    Point PXY = getViewOnScreenXY(parent);

    Point point = new Point();
    point.x = cXY.x - PXY.x;
    point.y = cXY.y - PXY.y;
    return point;
  }

  /**
   * 添加一个OnGlobalLayoutListener 并且让这个监听器只执行一次
   */
  public static void addOnceOnGlobalLayoutListener(final View v, final DoSomeThing someThing) {

    if (someThing == null || v == null) return;

    ViewTreeObserver viewTreeObserver = v.getViewTreeObserver();
    viewTreeObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

      @Override public void onGlobalLayout() {

        someThing.doSomeThing(v);

        v.getViewTreeObserver().removeGlobalOnLayoutListener(this);
      }
    });
  }

  /**
   *
   * @param v
   * @param height
   */
  public static void setHeight(View v, int height) {

    LayoutParams lp = v.getLayoutParams();
    if (lp == null) {

      Yr.e("LayoutParams 还未初始化~");
      return;
    }
    if (v == null) {

      Yr.e("view == null");
      return;
    }

    lp.height = height;

    v.setLayoutParams(lp);
  }

  /**
   *
   * @param v
   * @param width
   */
  public static void setWidth(View v, int width) {

    LayoutParams lp = v.getLayoutParams();
    if (lp == null) {

      Yr.e("LayoutParams 还未初始化~");
      return;
    }
    if (v == null) {

      Yr.e("view == null");
      return;
    }

    lp.width = width;

    v.setLayoutParams(lp);
  }

  @SuppressLint("NewApi")
  public static void addOnceOnDrawListener(final View v, final DoSomeThing someThing) {

    if (someThing == null || v == null) return;

    ViewTreeObserver viewTreeObserver = v.getViewTreeObserver();
    viewTreeObserver.addOnDrawListener(new OnDrawListener() {

      @Override public void onDraw() {

        someThing.doSomeThing(v);

        v.getViewTreeObserver().removeOnDrawListener(this);
      }
    });
  }

  /**
   * 方便获取Paint对象而已
   */
  public static Paint newPaint(int color) {

    Paint paint = new Paint();

    paint.setColor(color);

    paint.setAntiAlias(true);

    return paint;
  }

  @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
  public static void setSelector(View view, Drawable drawable, Drawable preDrawable) {
    view.setClickable(true);
    view.setBackground(newSelectorForPress(view.getContext(), drawable, preDrawable));
  }

  @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
  public static void setSrcSelector(ImageView imageView, Drawable drawable, Drawable preDrawable) {
    imageView.setClickable(true);
    imageView.setImageDrawable(newSelectorForPress(imageView.getContext(), drawable, preDrawable));
  }

  @TargetApi(Build.VERSION_CODES.JELLY_BEAN) private void setSelector(View view) {
    view.setClickable(true);
    if (view instanceof ImageView) {
      Drawable drawable = ((ImageView) view).getDrawable();
      if (drawable != null) {
        ((ImageView) view).setImageDrawable(new SelectorDrawable(drawable));
        Yr.d();
      }
      return;
    }
    Drawable background = view.getBackground();
    if (background != null) {
      view.setBackground(new SelectorDrawable(background));
      Yr.d();
    }
  }

  /**
   * 只对没有设置背景背景好用 | 单一颜色的shape
   */
  @TargetApi(Build.VERSION_CODES.JELLY_BEAN) public static void setDefaultSelector(View view) {
    if (view == null) {
      return;
    }
    Drawable background = view.getBackground();
    if (background == null) {
      setSelector(view, new ColorDrawable(0x00000000), new ColorDrawable(0x09000000));
      return;
    }
    if (background instanceof GradientDrawable) {
      try {
        GradientDrawable bg =
            (GradientDrawable) background.getConstantState().newDrawable().mutate();
        Class<?> gradientStateClass =
            Class.forName("android.graphics.drawable.GradientDrawable$GradientState");
        Field mColorsField = gradientStateClass.getDeclaredField("mColors");
        mColorsField.setAccessible(true);
        Paint paint = null;
        Field[] declaredFields = GradientDrawable.class.getDeclaredFields();
        for (int i = 0; i < declaredFields.length; i++) {
          declaredFields[i].setAccessible(true);
          Yr.d(declaredFields[i].getType());
          if (declaredFields[i].getType() == Paint.class) {
            paint = (Paint) declaredFields[i].get(bg);
            if (paint == null) {
              continue;
            } else {
              break;
            }
          }
        }
        Yr.d(paint);
        int color = getDefaultPressColor(paint.getColor());
        bg.setColors(new int[] {
            color, color
        });
        setSelector(view, background, bg);
      } catch (Exception e) {
        Yr.logError("设置selector失败", e);
      }
    }

    if (background instanceof ColorDrawable) {

      ColorDrawable colorDrawable = (ColorDrawable) background;
      setSelector(view, background,
          new ColorDrawable(getDefaultPressColor(colorDrawable.getColor())));
    }
  }

  private static int getDefaultPressColor(int color) {
    return 0xee << 24 | color & 0x00FFFFFF;
  }

  public static void setEditTextLast(EditText editText) {
    Editable etext = editText.getText();
    Selection.setSelection(etext, etext.length());
  }

  public static interface DoSomeThing {

    void doSomeThing(View v);
  }

  public static abstract class ParamsDoSomeThing implements DoSomeThing {

    Object[] params;

    public ParamsDoSomeThing(Object... params) {
      this.params = params;
    }

    @Override public void doSomeThing(View v) {

      doSomeThing(v, params);
    }

    public abstract void doSomeThing(View v, Object[] params);
  }

  /*
   * phoneWindow$DecorView---LinerLayout--- |---ActionBarContainer
   * ------------ |---|FrameLayout| ------------ |---ActionBarContainer
   */
  public static FrameLayout getRootView(Activity activity) {

    FrameLayout decorView = (FrameLayout) activity.getWindow().getDecorView();

    return decorView;
  }

  /**
   *
   * @param view
   * @param from
   * @param to
   * @param duration
   * @param onChangeListener
   */
  @SuppressLint("NewApi") public static void changeHeight(final View view, final int from,
      final int to, final long duration, final OnChangeListener onChangeListener) {

    new AsyncTask<Void, Integer, Void>() {

      @Override protected Void doInBackground(Void... params) {

        if (onChangeListener != null) {
          onChangeListener.onBeforeChange(from);
        }
        if (to > from) {

          int diff = to - from;

          long sleep = duration / diff;

          for (int i = from; i <= to; i++) {

            publishProgress(i);

            try {
              Thread.sleep(sleep);
            } catch (InterruptedException e) {
              Yr.logError(e);
            }
          }
        } else {

          int diff = from - to;

          long sleep = duration / diff;

          for (int i = from; i >= to; i--) {

            publishProgress(i);

            try {
              Thread.sleep(sleep);
            } catch (InterruptedException e) {
              Yr.logError(e);
            }
          }
        }

        return null;
      }

      @Override protected void onProgressUpdate(Integer[] values) {

        if (onChangeListener != null) {
          onChangeListener.onChanging(values[0]);
        }

        YViews.setViewHeight(view, values[0]);
      }

      ;

      @Override protected void onPostExecute(Void result) {

        if (onChangeListener != null) {
          onChangeListener.onChanged(to);
        }
      }
    }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
  }

  /**
   *
   * @param view
   * @param from
   * @param to
   * @param duration
   * @param onChangeListener
   */
  @SuppressLint("NewApi") public static void changeWidth(final View view, final int from,
      final int to, final long duration, final OnChangeListener onChangeListener) {

    new AsyncTask<Void, Integer, Void>() {

      @Override protected Void doInBackground(Void... params) {

        if (onChangeListener != null) {
          onChangeListener.onBeforeChange(from);
        }
        if (to > from) {

          int diff = to - from;

          long sleep = duration / diff;

          for (int i = from; i <= to; i++) {

            publishProgress(i);

            try {
              Thread.sleep(sleep);
            } catch (InterruptedException e) {
              Yr.logError(e);
            }
          }
        } else {

          int diff = from - to;

          long sleep = duration / diff;

          for (int i = from; i >= to; i--) {

            publishProgress(i);

            try {
              Thread.sleep(sleep);
            } catch (InterruptedException e) {
              Yr.logError(e);
            }
          }
        }

        return null;
      }

      @Override protected void onProgressUpdate(Integer[] values) {

        if (onChangeListener != null) {
          onChangeListener.onChanging(values[0]);
        }

        YViews.setViewWidth(view, values[0]);
      }

      ;

      @Override protected void onPostExecute(Void result) {

        if (onChangeListener != null) {
          onChangeListener.onChanged(to);
        }
      }
    }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
  }

  /**
   *
   * @param from
   * @param to
   * @param duration
   * @param onChangeListener
   */
  @SuppressLint("NewApi") public static void changing(final int from, final int to,
      final long duration, final OnChangeListener onChangeListener) {

    new AsyncTask<Void, Integer, Void>() {

      @Override protected Void doInBackground(Void... params) {

        if (onChangeListener != null) {
          onChangeListener.onBeforeChange(from);
        }

        if (to > from) {

          int diff = to - from;

          if (diff == 0) {
            return null;
          }

          long sleep = duration / diff;

          for (int i = from; i <= to; i++) {

            publishProgress(i);

            try {
              Thread.sleep(sleep);
            } catch (InterruptedException e) {
              Yr.logError(e);
            }
          }
        } else {

          int diff = from - to;

          if (diff == 0) {
            return null;
          }

          long sleep = duration / diff;

          for (int i = from; i >= to; i--) {

            publishProgress(i);

            try {
              Thread.sleep(sleep);
            } catch (InterruptedException e) {
              Yr.logError(e);
            }
          }
        }

        return null;
      }

      @Override protected void onProgressUpdate(Integer[] values) {

        if (onChangeListener != null) {
          onChangeListener.onChanging(values[0]);
        }
      }

      ;

      @Override protected void onPostExecute(Void result) {

        if (onChangeListener != null) {
          onChangeListener.onChanged(to);
        }
      }
    }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
  }

  /** 设置Selector。 */
  public static StateListDrawable newSelector(Context context, int idNormal, int idPressed,
      int idFocused, int idUnable) {

    StateListDrawable bg = new StateListDrawable();
    Drawable normal = idNormal == -1 ? null : context.getResources().getDrawable(idNormal);
    Drawable pressed = idPressed == -1 ? null : context.getResources().getDrawable(idPressed);
    Drawable focused = idFocused == -1 ? null : context.getResources().getDrawable(idFocused);
    Drawable unable = idUnable == -1 ? null : context.getResources().getDrawable(idUnable);
    // View.PRESSED_ENABLED_STATE_SET
    bg.addState(new int[] {
        android.R.attr.state_pressed, android.R.attr.state_enabled
    }, pressed);
    // View.ENABLED_FOCUSED_STATE_SET
    bg.addState(new int[] {
        android.R.attr.state_enabled, android.R.attr.state_focused
    }, focused);
    // View.ENABLED_STATE_SET
    bg.addState(new int[] { android.R.attr.state_enabled }, normal);
    // View.FOCUSED_STATE_SET
    bg.addState(new int[] { android.R.attr.state_focused }, focused);
    // View.WINDOW_FOCUSED_STATE_SET
    bg.addState(new int[] { android.R.attr.state_window_focused }, unable);
    // View.EMPTY_STATE_SET
    bg.addState(new int[] {}, normal);
    return bg;
  }

  /** 设置Selector。 */
  public static StateListDrawable newSelectorForPress(Context context, int idNormal,
      int idPressed) {

    StateListDrawable bg = new StateListDrawable();
    Drawable normal = idNormal == -1 ? null : context.getResources().getDrawable(idNormal);
    Drawable pressed = idPressed == -1 ? null : context.getResources().getDrawable(idPressed);
    // View.PRESSED_ENABLED_STATE_SET
    bg.addState(new int[] {
        android.R.attr.state_pressed, android.R.attr.state_enabled
    }, pressed);
    // View.FOCUSED_STATE_SET
    bg.addState(new int[] {}, normal);
    return bg;
  }

  /** 设置Selector。 */
  public static StateListDrawable newSelectorForPress(Context context, Bitmap bmNor, Bitmap bmPre) {

    if (bmNor == null || bmPre == null) {
      Yr.e("newSelectorForPress-->bm==null");
      return null;
    }
    StateListDrawable bg = new StateListDrawable();
    Drawable normal = new BitmapDrawable(context.getResources(), bmNor);
    Drawable pressed = new BitmapDrawable(context.getResources(), bmPre);
    // View.PRESSED_ENABLED_STATE_SET
    bg.addState(new int[] {
        android.R.attr.state_pressed, android.R.attr.state_enabled
    }, pressed);
    // View.FOCUSED_STATE_SET
    bg.addState(new int[] {}, normal);
    return bg;
  }

  /** 设置Selector。 */
  public static StateListDrawable newSelectorForPress(Context context, Drawable normal,
      Drawable pressed) {

    if (normal == null || pressed == null) {
      Yr.e("newSelectorForPress-->bm==null");
      return null;
    }
    StateListDrawable bg = new StateListDrawable();
    // View.PRESSED_ENABLED_STATE_SET
    bg.addState(new int[] {
        android.R.attr.state_pressed, android.R.attr.state_enabled
    }, pressed);
    // View.FOCUSED_STATE_SET
    bg.addState(new int[] {}, normal);
    return bg;
  }

  public static ColorStateList newColorStateList(int normal, int pressed, int focused, int unable) {

    int[] colors = new int[] {
        pressed, focused, normal, focused, unable, normal
    };
    int[][] states = new int[6][];
    states[0] = new int[] {
        android.R.attr.state_pressed, android.R.attr.state_enabled
    };
    states[1] = new int[] {
        android.R.attr.state_enabled, android.R.attr.state_focused
    };
    states[2] = new int[] { android.R.attr.state_enabled };
    states[3] = new int[] { android.R.attr.state_focused };
    states[4] = new int[] { android.R.attr.state_window_focused };
    states[5] = new int[] {};
    ColorStateList colorList = new ColorStateList(states, colors);
    return colorList;
  }

  public static interface OnChangeListener {

    void onChanging(int value);

    void onChanged(int value);

    void onBeforeChange(int value);
  }

  public static ImageView getFirstImageView(ViewGroup vg) {

    for (int i = 0; i < vg.getChildCount(); i++) {

      View childAt = vg.getChildAt(i);

      if (childAt instanceof ImageView) {

        return (ImageView) childAt;
      }
    }
    return null;
  }

  /**
   * 判断两个矩形是否重叠
   */
  public static boolean isOverlapping(Rect rectA, Rect rectB) {

    if (rectA.contains(rectB.left, rectB.top)
        || rectA.contains(rectB.right, rectB.top)
        || rectA.contains(rectB.left, rectB.bottom)
        || rectA.contains(rectB.right, rectB.bottom)) {
      return true;
    }
    if (rectB.contains(rectA.left, rectA.top)
        || rectB.contains(rectA.right, rectA.top)
        || rectB.contains(rectA.left, rectA.bottom)
        || rectB.contains(rectA.right, rectA.bottom)) {
      return true;
    }
    if (rectA.contains(rectB)) {
      return true;
    }
    if (rectB.contains(rectA)) {
      return true;
    }
    return false;
  }

  /**
   * 获得状态栏的高度
   */
  public static int getStatusHeight(Context context) {

    int statusHeight = -1;
    try {
      Class<?> clazz = Class.forName("com.android.internal.R$dimen");
      Object object = clazz.newInstance();
      int height = Integer.parseInt(clazz.getField("status_bar_height").get(object).toString());
      statusHeight = context.getResources().getDimensionPixelSize(height);
    } catch (Exception e) {
      e.printStackTrace();
    }
    return statusHeight;
  }

  /**
   * 获取当前屏幕截图，包含状态栏
   */
  public static Bitmap snapShotWithStatusBar(Activity activity) {
    View view = activity.getWindow().getDecorView();
    view.setDrawingCacheEnabled(true);
    view.buildDrawingCache();
    Bitmap bmp = view.getDrawingCache();
    int width = getScreenWidth(activity);
    int height = getScreenHeight(activity);
    Bitmap bp = null;
    bp = Bitmap.createBitmap(bmp, 0, 0, width, height);
    view.destroyDrawingCache();
    return bp;
  }

  /**
   * 获取当前屏幕截图，不包含状态栏
   */
  public static Bitmap snapShotWithoutStatusBar(Activity activity) {
    View view = activity.getWindow().getDecorView();
    view.setDrawingCacheEnabled(true);
    view.buildDrawingCache();
    Bitmap bmp = view.getDrawingCache();
    Rect frame = new Rect();
    activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
    int statusBarHeight = frame.top;

    int width = getScreenWidth(activity);
    int height = getScreenHeight(activity);
    Bitmap bp = null;
    bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height - statusBarHeight);
    view.destroyDrawingCache();
    return bp;
  }

  /**
   * 遍历所有View
   */
  public static void traverseView(View vg, ViewHandler handler) {

    handler.handlerView(vg);

    if (vg instanceof ViewGroup) {

      ViewGroup group = (ViewGroup) vg;

      int childCount = group.getChildCount();

      for (int i = 0; i < childCount; i++) {

        View childView = group.getChildAt(i);

        traverseView(childView, handler);
      }
    }
  }

  @SuppressLint("NewApi")
  public static void applyLoading(Context context, RelativeLayout relativeLayout, int count,
      int margin, final int sleepTime, final int detalY) {
    final int APPLYLOADING_ID_HEAD = 20000;

    final List<View> fgViews = new ArrayList<View>();
    final List<View> bgViews = new ArrayList<View>();
    int childCount = relativeLayout.getChildCount();

    if (childCount < 2) {
      Yr.logError(new Exception("必须传两个以上子View"));
      return;
    }
    View bgView = relativeLayout.getChildAt(0);

    Drawable bgBackground = bgView.getBackground();

    View fgView = relativeLayout.getChildAt(1);

    Drawable fgBackground = fgView.getBackground();

    bgView.setVisibility(View.INVISIBLE);

    fgView.setVisibility(View.INVISIBLE);

    RelativeLayout.LayoutParams bgLayoutParams =
        (RelativeLayout.LayoutParams) bgView.getLayoutParams();

    RelativeLayout.LayoutParams fgLayoutParams =
        (RelativeLayout.LayoutParams) fgView.getLayoutParams();

    for (int i = 0; i < count; i++) {

      // 背景
      View copyBgView = new View(context);

      // RelativeLayout.LayoutParams copyBgLayoutParams = new
      // RelativeLayout.LayoutParams(
      // bgLayoutParams);

      copyBgView.setBackground(bgBackground);

      copyBgView.setTranslationX(i * margin);

      relativeLayout.addView(copyBgView, bgLayoutParams);

      bgViews.add(copyBgView);
      // 前景
      View copyFgView = new View(context);

      // RelativeLayout.LayoutParams copyFgLayoutParams = new
      // android.widget.RelativeLayout.LayoutParams(
      // fgLayoutParams);
      copyFgView.setBackground(fgBackground);

      copyFgView.setTranslationX(i * margin);

      relativeLayout.addView(copyFgView, fgLayoutParams);

      fgViews.add(copyFgView);
    }
    // 启动动画

    final Handler handler = new Handler();

    new AsyncTask<Void, Void, Void>() {

      @Override protected Void doInBackground(Void... paramVarArgs) {

        try {
          Thread.sleep(200);
        } catch (InterruptedException e1) {
          e1.printStackTrace();
        }
        for (int i = 0; i < fgViews.size(); i++) {

          final View fgView = fgViews.get(i);
          final View bgView = bgViews.get(i);

          handler.postDelayed(new Runnable() {
            @Override public void run() {
              float alpha = 0.2f;

              ObjectAnimator fgAnimator =
                  ObjectAnimator.ofFloat(fgView, S.Ani.TRANSLATIONY, 0, detalY, 0);
              fgAnimator.setRepeatCount(-1);
              fgAnimator.setDuration(1000).start();

              ObjectAnimator fgAlphaAnimator =
                  ObjectAnimator.ofFloat(fgView, S.Ani.ALPHA, alpha, 1, alpha);
              fgAlphaAnimator.setRepeatCount(-1);
              fgAlphaAnimator.setDuration(1000).start();

              // ObjectAnimator bgAnimator = ObjectAnimator
              // .ofFloat(bgView, S.Ani.TRANSLATIONY, 0.2f,
              // -75, 0.2f);
              // bgAnimator.setRepeatCount(-1);
              // bgAnimator.setDuration(1000).start();
              //
              // ObjectAnimator bgAlphaAnimator = ObjectAnimator
              // .ofFloat(bgView, S.Ani.ALPHA, 0.2f, 1, 0.2f);
              // bgAlphaAnimator.setRepeatCount(-1);
              // bgAlphaAnimator.setDuration(1000).start();
            }
          }, 0);

          try {

            Thread.sleep(sleepTime);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
        return null;
      }
    }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
  }

  public static class LoadingApplyer {

    private Context context;
    private RelativeLayout relativeLayout;
    private int count;
    private int margin;
    private int sleepTime;
    private int detalY;
    private List<View> fgViews;
    private List<View> bgViews;

    final Handler handler = new Handler();
    private List<List<ObjectAnimator>> animatorss;

    private boolean isStarted;

    @SuppressLint("NewApi")
    public LoadingApplyer applyLoading(Context context, RelativeLayout relativeLayout, int count,
        int margin, final int sleepTime, final int detalY) {
      this.context = context;
      this.relativeLayout = relativeLayout;
      this.count = count;
      this.margin = margin;
      this.sleepTime = sleepTime;
      this.detalY = detalY;
      final int APPLYLOADING_ID_HEAD = 20000;
      fgViews = new ArrayList<View>();
      bgViews = new ArrayList<View>();

      animatorss = new ArrayList<List<ObjectAnimator>>();

      int childCount = relativeLayout.getChildCount();

      if (childCount < 2) {
        Yr.logError(new Exception("必须传两个以上子View"));
        return null;
      }
      View bgView = relativeLayout.getChildAt(0);

      Drawable bgBackground = bgView.getBackground();

      View fgView = relativeLayout.getChildAt(1);

      Drawable fgBackground = fgView.getBackground();

      bgView.setVisibility(View.INVISIBLE);

      fgView.setVisibility(View.INVISIBLE);

      RelativeLayout.LayoutParams bgLayoutParams =
          (RelativeLayout.LayoutParams) bgView.getLayoutParams();

      RelativeLayout.LayoutParams fgLayoutParams =
          (RelativeLayout.LayoutParams) fgView.getLayoutParams();

      for (int i = 0; i < count; i++) {

        // 背景
        View copyBgView = new View(context);

        // RelativeLayout.LayoutParams copyBgLayoutParams = new
        // RelativeLayout.LayoutParams(
        // bgLayoutParams);

        copyBgView.setBackground(bgBackground);

        copyBgView.setTranslationX(i * margin);

        relativeLayout.addView(copyBgView, bgLayoutParams);

        bgViews.add(copyBgView);
        // 前景
        View copyFgView = new View(context);

        // RelativeLayout.LayoutParams copyFgLayoutParams = new
        // android.widget.RelativeLayout.LayoutParams(
        // fgLayoutParams);
        copyFgView.setBackground(fgBackground);

        copyFgView.setTranslationX(i * margin);

        relativeLayout.addView(copyFgView, fgLayoutParams);

        fgViews.add(copyFgView);
      }

      // 初始化动画
      for (int i = 0; i < fgViews.size(); i++) {

        final View fgView2 = fgViews.get(i);
        // final View bgView = bgViews.get(i);

        float alpha = 0.2f;

        ObjectAnimator fgAnimator =
            ObjectAnimator.ofFloat(fgView2, S.Ani.TRANSLATIONY, 0, detalY, 0);
        fgAnimator.setRepeatCount(-1);
        fgAnimator.setDuration(1000);

        ObjectAnimator fgAlphaAnimator =
            ObjectAnimator.ofFloat(fgView2, S.Ani.ALPHA, alpha, 1, alpha);
        fgAlphaAnimator.setRepeatCount(-1);
        fgAlphaAnimator.setDuration(1000);

        List<ObjectAnimator> animators = new ArrayList<ObjectAnimator>();
        animators.add(fgAnimator);
        animators.add(fgAlphaAnimator);

        animatorss.add(animators);
        // ObjectAnimator bgAnimator = ObjectAnimator
        // .ofFloat(bgView, S.Ani.TRANSLATIONY, 0.2f,
        // -75, 0.2f);
        // bgAnimator.setRepeatCount(-1);
        // bgAnimator.setDuration(1000).start();
        //
        // ObjectAnimator bgAlphaAnimator =
        // ObjectAnimator
        // .ofFloat(bgView, S.Ani.ALPHA, 0.2f, 1, 0.2f);
        // bgAlphaAnimator.setRepeatCount(-1);
        // bgAlphaAnimator.setDuration(1000).start();
      }
      return this;
    }

    @SuppressLint("NewApi") public void start() {

      if (isStarted) {
        return;
      }
      new AsyncTask<Void, Void, Void>() {

        @Override protected Void doInBackground(Void... paramVarArgs) {

          try {
            Thread.sleep(100);
          } catch (InterruptedException e1) {
            e1.printStackTrace();
          }
          for (int i = 0; i < fgViews.size(); i++) {

            final List<ObjectAnimator> animators = animatorss.get(i);

            handler.postDelayed(new Runnable() {
              @SuppressLint("NewApi") @Override public void run() {

                for (ObjectAnimator animator : animators) {

                  animator.start();
                }
              }
            }, 0);

            try {

              Thread.sleep(sleepTime);
            } catch (InterruptedException e) {
              e.printStackTrace();
            }
          }
          return null;
        }
      }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

      isStarted = true;
    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB) public void stop() {

      Yr.e();
      for (List<ObjectAnimator> animators : animatorss) {
        for (ObjectAnimator animator : animators) {
          animator.cancel();
        }
      }
      isStarted = false;
    }
  }

  // private static android.widget.RelativeLayout.LayoutParams
  // copyLayoutParams(
  // android.widget.RelativeLayout.LayoutParams lp) {
  // android.widget.RelativeLayout.LayoutParams newLp = new
  // android.widget.RelativeLayout.LayoutParams(
  // lp.width, lp.height);
  // newLp.setMargins(lp.leftMargin, lp.topMargin, lp.rightMargin,
  // lp.bottomMargin);
  //
  // int[] rules = lp.getRules();
  //
  // for (int i = 0; i < rules.length; i++) {
  //
  //
  // }
  //
  // return null;
  // }

  /**
   * 获取view的OnClickListener
   */
  public static OnClickListener getOnClickListener(View view) {

    OnClickListener listener = null;
    try {

      Method getListenerInfoMethod = View.class.getDeclaredMethod("getListenerInfo");

      getListenerInfoMethod.setAccessible(true);

      Object listenerInfo = getListenerInfoMethod.invoke(view);

      Field mOnClickListenerField = listenerInfo.getClass().getDeclaredField("mOnClickListener");

      mOnClickListenerField.setAccessible(true);

      listener = (OnClickListener) mOnClickListenerField.get(listenerInfo);
    } catch (Exception e) {

      Yr.logError(e);
    }
    return listener;
  }

  /**
   * 当软键盘显示隐藏发生变化时触发
   */
  @SuppressLint("NewApi") public static void addOnSoftInputListener(final EditText et,
      final OnSoftInputListener onSoftInputListener) {

    if (et == null) {
      Yr.logError(new Exception("EditText is null when addOnSoftInputListener"));
      return;
    }
    et.addOnLayoutChangeListener(new OnLayoutChangeListener() {

      @Override
      public void onLayoutChange(final View v, final int left, final int top, final int right,
          final int bottom, final int oldLeft, final int oldTop, final int oldRight,
          final int oldBottom) {
        // 在这里判断软键盘的弹出状态 更改listview的高度 listview是above在listBottom 上

        if (onSoftInputListener != null) {

          new Handler().postDelayed(new Runnable() {

            @Override public void run() {
              onSoftInputListener.onChange(v, left, top, right, bottom, oldLeft, oldTop, oldRight,
                  oldBottom, YSystems.getSoftInputHeight(et));
            }
          }, 200);
        }
      }
    });
  }

  public static interface OnSoftInputListener {
    /**
     * @param height 软件盘高度
     */
    void onChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop,
        int oldRight, int oldBottom, int height);
  }

  public static <T extends View> T getFirstView(View v, Class<T> viewClass) {

    if (v instanceof ViewGroup) {

      ViewGroup vg = (ViewGroup) v;

      for (int i = 0; i < vg.getChildCount(); i++) {

        View childAt = vg.getChildAt(i);

        if (childAt.getClass() == viewClass) {

          return (T) childAt;
        }
      }
    } else {
      return (T) v;
    }
    return null;
  }

  public static void setAllViewsSelected(View v, final boolean isSel) {

    YViews.traverseView(v, new ViewHandler() {

      @Override public void handlerView(View v) {
        v.setSelected(isSel);
      }
    });
  }

  public static void setSelectorDrawable(View... views) {
    for (View view : views) {
      if (view instanceof ImageView) {
        ImageView iv = (ImageView) view;
        Drawable drawable = iv.getDrawable();
        iv.setImageDrawable(new SelectorDrawable(drawable));
      } else {
        Drawable background = view.getBackground();
        if (background == null) {
          background = new ColorDrawable(0xffffffff);
        }
        view.setBackground(new SelectorDrawable(background));
      }
    }
  }

  /**
   * 设置textview部分颜色
   */
  public static void setTextViewColorSpan(TextView tv, CharSequence str,
      SpanColorHolder... colorHolders) {

    if (colorHolders == null || colorHolders.length == 0) {
      tv.setText(str);
      return;
    }
    SpannableStringBuilder builder = new SpannableStringBuilder(str);

    for (int i = 0; i < colorHolders.length; i++) {
      SpanColorHolder holder = colorHolders[i];
      ForegroundColorSpan span = new ForegroundColorSpan(holder.color);
      builder.setSpan(span, holder.start, holder.end, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
    }
    tv.setText(builder);
    // ForegroundColorSpan 为文字前景色，BackgroundColorSpan为文字背景色
  }
  @RequiresApi(api = VERSION_CODES.HONEYCOMB)
  public static void copy(TextView textView) {
    ClipboardManager cmb = (ClipboardManager) textView.getContext().getSystemService(Context.CLIPBOARD_SERVICE);
    cmb.setText(textView.getText()); //将内容放入粘贴管理器,在别的地方长按选择"粘贴"即可
  }

  public static void setTextViewSpan(TextView tv, String str, SpanHolder... holders) {

    if (holders == null || holders.length == 0) {
      tv.setText(str);
      return;
    }
    SpannableStringBuilder builder = new SpannableStringBuilder(str);

    for (int i = 0; i < holders.length; i++) {
      SpanHolder holder = holders[i];
      //ForegroundColorSpan span = new ForegroundColorSpan(holder.color);
      builder.setSpan(holder.span, holder.start, holder.end,
          Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
    }
    tv.setText(builder);
    // ForegroundColorSpan 为文字前景色，BackgroundColorSpan为文字背景色
  }

  public static class SpanColorHolder {
    int start;
    int end;
    int color;

    public SpanColorHolder(int start, int end, int color) {
      super();
      this.start = start;
      this.end = end;
      this.color = color;
    }
  }

  public static class SpanHolder {
    int start;
    int end;
    CharacterStyle span;

    public SpanHolder(int start, int end, CharacterStyle span) {
      super();
      this.start = start;
      this.end = end;
      this.span = span;
    }
  }

  /**
   * 记录listview当前的滚动位置
   *
   * @author yorun
   */
  public static class ListViewScrollYSaver {
    private int index;
    private int top;
    ListView listView;

    public ListViewScrollYSaver(ListView listView) {
      super();
      this.listView = listView;
    }

    public void save() {
      index = listView.getFirstVisiblePosition();
      View vv = listView.getChildAt(0);
      top = (vv == null) ? 0 : vv.getTop();
    }

    public void restoreScrollY() {
      listView.setSelectionFromTop(index, top);
    }
  }

  public static interface ViewHandler {

    void handlerView(View v);
  }
  public static interface ViewHandlerForReturn<T> {

    T handlerView(View v);
  }
}
